package diagram;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Assistant de gestion des listeners d'évènements de sélection d'un ModelElement.
 * 
 * @author  A. Estebe
 *
 */
public class ElementSelectionSupport {

	/**
	 * L'ensemble des listeners.
	 * 
	 * <p>
	 * On utilise des WeakReference pour éviter d'empêcher la récupération mémoire des objets. ( bonne pratique )
	 * </p>
	 */
	private List<WeakReference<ElementSelectionListener>> elementSelectedListeners = new ArrayList<WeakReference<ElementSelectionListener>>();

	/**
	 * Ajoute un listener à l'ensemble des listeners.
	 * 
	 * @param listener l'instance de {@link ElementSelectionListener} à ajouter.
	 */
	public void addElementSelectedListener(ElementSelectionListener listener) {
		WeakReference<ElementSelectionListener> ref = new WeakReference<ElementSelectionListener>(
				listener);
		elementSelectedListeners.add(ref);
	}

	/**
	 * Retire un listener de l'ensemble des listeners enregistrés.
	 * 
	 * <br><em>Nota: retire les enregistrements multiples</em>
	 * 
	 * @param listener l'instance de {@link ElementSelectionListener} à retirer.
	 */
	public void removeElementSelectedListener(ElementSelectionListener listener) {
		Iterator<WeakReference<ElementSelectionListener>> iterator = elementSelectedListeners
				.iterator();
		// Parcours de l'ensemble des valeurs
		while (iterator.hasNext()) {
			// Récupération de la référence "weak"
			WeakReference<ElementSelectionListener> ref = iterator.next();
			// Récupération de la référence normale
			ElementSelectionListener hardRef = ref.get();
			if (null == hardRef) {
				// l'instance a été récupérée par la JVM, il faut nettoyer
				iterator.remove();
			} else if (hardRef.equals(listener)) {
				// C'est un enregistrement du listener, on l'enlève
				iterator.remove();
			}
		}
	}

	/**
	 * Fonction d'activation des listeners d'évènement pour la sélection d'un élément.
	 * 
	 * @param event l'évènement à propager.
	 */
	public void fireElementSelectedEvent(ElementSelectionEvent event) {
		Iterator<WeakReference<ElementSelectionListener>> iterator = elementSelectedListeners
				.iterator();
		// Parcours de l'ensemble des valeurs
		while (iterator.hasNext()) {
			// Récupération de la référence "weak"
			WeakReference<ElementSelectionListener> ref = iterator.next();
			// Récupération de la référence normale
			ElementSelectionListener hardRef = ref.get();
			if (null == hardRef) {
				// l'instance a été récupérée par la JVM, il faut nettoyer
				iterator.remove();
			} else {
				// Activation de la méthode de callback
				hardRef.elementSelected(event);
			}
		}

	}

	/**
	 * Fonction d'activation des listeners d'évènement pour la désélection d'un élément.
	 * 
	 * @param event l'évènement à propager.
	 */
	public void fireElementDeselectedEvent(ElementSelectionEvent event) {
		Iterator<WeakReference<ElementSelectionListener>> iterator = elementSelectedListeners
				.iterator();
		// Parcours de l'ensemble des valeurs
		while (iterator.hasNext()) {
			// Récupération de la référence "weak"
			WeakReference<ElementSelectionListener> ref = iterator.next();
			// Récupération de la référence normale
			ElementSelectionListener hardRef = ref.get();
			if (null == hardRef) {
				// l'instance a été récupérée par la JVM, il faut nettoyer
				iterator.remove();
			} else {
				// Activation de la méthode de callback
				hardRef.elementDeselected(event);
			}
		}

	}
}
